package com.pubinfo.passbook.common.utils;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.pubinfo.passbook.common.entity.TContractBase;
import com.pubinfo.passbook.common.model.bo.Excel;
import com.pubinfo.passbook.common.model.bo.contract.ContractStatus;
import com.pubinfo.passbook.common.service.contract.TContractBaseService;
import com.pubinfo.passbook.common.service.master.TSubsidiaryInfoService;
import com.pubinfo.passbook.common.service.master.TSubsidiaryPrivateKeyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class ContractStatusListener extends AnalysisEventListener<ContractStatus> {
  
  private static final int BATCH_COUNT = 10000;
  List<ContractStatus> list = new ArrayList();
  
  private TContractBaseService baseService;
  
  public List<ContractStatus> getList() {
    return list;
  }
  
  /**
   * 假设这个是一个DAO，当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
   */
  private TSubsidiaryPrivateKeyService keyService;
  private TSubsidiaryInfoService infoService;
  private String acct;
  
  public ContractStatusListener(String acct, TContractBaseService baseService) {
    this.baseService = baseService;
    this.acct = acct;
  }
  
  public ContractStatusListener() {
    // 这里是demo，所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
    //    uploadDAO = new TAutoInterfaceService();
  }
  
  /**
   * 加上存储数据库
   */
  @Transactional
  public void saveData() {
    
    for (ContractStatus contractStatus : list) {
      //只保存状态
      Integer status = contractStatus.getStatus();
      baseService.lambdaUpdate().set(status != null, TContractBase::getStatus, status).set(TContractBase::getModifiedBy, acct).eq(TContractBase::getContractCode, contractStatus.getContractCode()).update();
    }
  }
  
  /**
   * 所有数据解析完成了 都会来调用
   *
   * @param context
   */
  @Override
  public void doAfterAllAnalysed(AnalysisContext context) {
    // 这里也要保存数据，确保最后遗留的数据也存储到数据库
    saveData();
    log.info("所有数据解析完成！");
  }
  
  private Boolean checkObjIsNull(Excel interfaceImport) {
    for (Field f : interfaceImport.getClass().getDeclaredFields()) {
      f.setAccessible(true);
      try {
        if (f.get(interfaceImport) == null || "".equals(f.get(interfaceImport).toString())) { //判断字段是否为空，并且对象属性中的基本都会转为对象类型来判断
          //  throw new ServiceException("请求参数不能为空");
        }
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      }
      
    }
    return true;
  }
  
  /**
   * 这个每一条数据解析都会来调用
   *
   * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
   * @param context
   */
  @Override
  public void invoke(ContractStatus data, AnalysisContext context) {
    log.info("解析到一条数据:{}", JSON.toJSONString(data));
    list.add(data);
    // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
    if (list.size() >= BATCH_COUNT) {
      saveData();
      // 存储完成清理 list
      list.clear();
    }
  }
}
